package com.spring.framework.config.life;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * 在此前基于XML的IoC配置文章中，我们说过，生命周期更长的bean中注入生命周期更短的bean时，可以使用查找方法注入
 * <lookup-method/>来解决短生命周期的bean实例的获取的问题，使得短生命周期的bean能够被正常管理。
 * <p>
 * 这里，@Scope注解也能解决这个问题。主要的就是设置它的proxyMode属性，使得注入的是一个代理对象，生命周期更长的
 * bean获取生命周期更短的bean实例时，实际上是通过代理对象去获取具有正常生命周期的bean实例的。
 * <p>
 * 如果我们的短生命周期bean实现了接口时，那么proxyMode可以选择设置为 ScopedProxyMode.INTERFACES，这表示将使
 * 用JDK动态代理来创建代理对象，代理对象同样实现这个接口；如果我们的短生命周期bean没有实现接口并且不是final类型
 * 时，那么proxyMode可以选择设置为ScopedProxyMode. TARGET_CLASS，这表示将使用CGLIB动态代理来创建代理对象，
 * 代理对象继承目标类。
 *
 * @author xuweizhi
 * @since 2020/12/15 10:04
 */
@Configuration
@ComponentScan(basePackages = {"com.spring.framework.config.life"})
public class LifeCycleConfig {

	public static void main(String[] args) {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(LifeCycleConfig.class);

		// 可以看到，虽然我们注入的bean是原型的，看是看起来并没有被成功控制，因为每次都是同一个原型bean对象，我们在@Scope注解中加上
		// proxyMode = ScopedProxyMode.TARGET_CLASS属性之后
		Singleton bean = context.getBean(Singleton.class);
		System.out.println(bean);
		System.out.println(bean.getPrototype());
		System.out.println(bean.getPrototype());

		System.out.println("-----------------");

		// 代理对象也行
		// 可以看到，每次获取原型对象都是获取的新建的对象，成功的控制了对象的生命周期为“原型”，这就是@Scope注解解决长生命周期的bean调
		// 用短生命周期的bean的问题，主要是靠proxyMode属性，相比于查找方法注入< lookup-method/>标签来说，是不是变得很简单了？
		Singleton bean2 = context.getBean(Singleton.class);
		System.out.println(bean2 == bean);
		System.out.println(bean2.getPrototype());
		System.out.println(bean2.getPrototype());
	}
}
